package com.fy.utils.fileUtils;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import com.fy.pojo.properties.AliOssProperties;
import com.fy.utils.aliyunUtils.AliOssUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Component
public class FileUploadTool {

    @Autowired
    private AliOssProperties aliOssProperties;

    @Autowired
    private AliOssUtil aliOssUtil;

    /**
     * 上传并合并文件分片
     *
     * @param chunk         文件分片数据
     * @param objectName    对象名称（原文件名）
     * @param index         当前分片索引
     * @param totalChunks   总分片数
     * @param uploadId      上传ID
     * @param newObjectName 新对象名称（随机生成的文件名）
     * @return 文件信息列表
     */
    public List<String> uploadAndMerge(byte[] chunk, String objectName, int index, int totalChunks, String uploadId,
            String newObjectName) {
        OSS ossClient = new OSSClientBuilder().build(aliOssProperties.getEndpoint(), aliOssProperties.getAccessKeyId(),
                aliOssProperties.getAccessKeySecret());
        List<String> list = new ArrayList<>();
        String url;

        if (uploadId == null || uploadId.isEmpty()) {
            // 初始化分片上传
            InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest(
                    aliOssProperties.getBucketName(), objectName);
            InitiateMultipartUploadResult initResult = ossClient.initiateMultipartUpload(initRequest);
            uploadId = initResult.getUploadId();
            log.info("uploadId为:{}", uploadId);
        }
        log.info("uploadId为:{}", uploadId);

        // 如果是最后一个分片，则合并所有分片
        if (index == totalChunks - 1) {
            // 上传分片
            uploadChunk(ossClient, chunk, index, uploadId, objectName);
            url = mergeChunks(ossClient, uploadId, totalChunks, objectName, newObjectName);
            // 删除临时分片（如果需要）
            // deleteChunks(ossClient, uploadId, objectName);
            list.add(null);
            list.add(url);
        } else if (index < totalChunks - 1) {
            uploadChunk(ossClient, chunk, index, uploadId, objectName);
            list.add(uploadId);
            list.add(null);
        }
        log.info("返回的list:{}", list);
        return list;
    }

    private void uploadChunk(OSS ossClient, byte[] chunk, int index, String uploadId, String objectName) {
        UploadPartRequest uploadRequest = new UploadPartRequest();
        uploadRequest.setBucketName(aliOssProperties.getBucketName());
        uploadRequest.setKey(objectName);
        uploadRequest.setUploadId(uploadId);
        uploadRequest.setPartNumber(index + 1);
        uploadRequest.setInputStream(new ByteArrayInputStream(chunk));

        ossClient.uploadPart(uploadRequest);
    }

    private String mergeChunks(OSS ossClient, String uploadId, int totalChunks, String objectName,
            String newObjectName) {
        List<PartETag> partETags = getPartETags(ossClient, uploadId, totalChunks, objectName);
        CompleteMultipartUploadRequest completeRequest = new CompleteMultipartUploadRequest(
                aliOssProperties.getBucketName(), objectName, uploadId, partETags);
        ossClient.completeMultipartUpload(completeRequest);

        // 重命名文件
        renameFile(ossClient, objectName, newObjectName);

        return getFileUrl(newObjectName);
    }

    private void renameFile(OSS ossClient, String oldObjectName, String newObjectName) {
        // 复制文件到新名称
        CopyObjectRequest copyObjectRequest = new CopyObjectRequest(aliOssProperties.getBucketName(), oldObjectName,
                aliOssProperties.getBucketName(), newObjectName);
        ossClient.copyObject(copyObjectRequest);

        // 删除旧文件
        ossClient.deleteObject(aliOssProperties.getBucketName(), oldObjectName);
    }

    private String getFileUrl(String newObjectName) {
        // 假设你的OSS服务是公开可访问的，这里返回的是一个公共URL
        return String.format("http://%s.%s/%s", aliOssProperties.getBucketName(), aliOssProperties.getEndpoint(),
                newObjectName);
    }

    private List<PartETag> getPartETags(OSS ossClient, String uploadId, int totalChunks, String objectName) {
        ListPartsRequest listPartsRequest = new ListPartsRequest(aliOssProperties.getBucketName(), objectName,
                uploadId);
        PartListing partListing = ossClient.listParts(listPartsRequest);
        List<PartSummary> partSummaries = partListing.getParts();
        List<PartETag> partETags = new ArrayList<>();
        for (PartSummary partSummary : partSummaries) {
            partETags.add(new PartETag(partSummary.getPartNumber(), partSummary.getETag()));
        }
        return partETags;
    }

    /**
     * 普通文件上传
     *
     * @param file 上传的文件
     * @return 阿里云文件路径
     */
    public String uploadFile(MultipartFile file) {
        // 生成新的文件名（可以根据实际需求进行修改）
        String newObjectName = generateNewFileName(file.getOriginalFilename());

        try (InputStream inputStream = file.getInputStream()) {
            // 创建OSSClient实例
            OSS ossClient = new OSSClientBuilder().build(aliOssProperties.getEndpoint(),
                    aliOssProperties.getAccessKeyId(),
                    aliOssProperties.getAccessKeySecret());

            // 上传文件到OSS
            PutObjectRequest putObjectRequest = new PutObjectRequest(aliOssProperties.getBucketName(), newObjectName,
                    inputStream);
            ossClient.putObject(putObjectRequest);

            // 获取文件的URL
            String fileUrl = getFileUrl(newObjectName);

            // 关闭OSSClient
            ossClient.shutdown();

            return fileUrl;
        } catch (IOException e) {
            log.error("文件上传失败", e);
            return null;
        }
    }

    private String generateNewFileName(String originalFileName) {
        // 这里可以根据实际需求生成新的文件名，例如添加时间戳等
        // 示例：在原文件名前添加当前时间戳
        long timestamp = System.currentTimeMillis();
        int dotIndex = originalFileName.lastIndexOf('.');
        String fileNameWithoutExtension = originalFileName.substring(0, dotIndex);
        String fileExtension = originalFileName.substring(dotIndex);
        return timestamp + "_" + fileNameWithoutExtension + fileExtension;
    }

    /**
     * 删除阿里云OSS中的文件
     * @param objectName 要删除的文件名
     * @return 如果删除成功返回true，否则返回false
     */
    public boolean deleteFile(String objectName) {
        log.info("Deleting object: {}", objectName);
        try {
            aliOssUtil.delete(objectName);
            log.info("阿里云存储数据删除成功: {}", objectName);
            return true;
        } catch (Exception e) {
            log.error("阿里云存储数据删除失败: {}, error: {}", objectName, e.getMessage());
            return false;
        }
    }
}
